﻿using System;
using System.Collections.Generic;
using System.IO;
using Xenta.Attributes;
using Xenta.Enums;
using Xenta.Operations;
using Xenta.Utils;

namespace Xenta.Api
{
    /// <summary>
    /// Represents the upload service.
    /// </summary>
    [Dependency("b737dbbb-6232-4954-8b18-83909c3bf0c9", 
        Lifestyle = DependencyLifestyle.Singleton)]
    public class UploadService : IHandler
    {
        #region Fields

        private readonly IInfrastructure _infrastructure;

        #endregion

        #region Ctors

        /// <summary>
        /// Initializes a new instance of the class.
        /// </summary>
        /// <param name="infrastructure">The infrastructure.</param>
        public UploadService(IInfrastructure infrastructure)
        {
            _infrastructure = infrastructure;
        }

        #endregion

        #region Methods

        /// <summary>
        /// Handles the input stream, using the ingoing properties, 
        /// and returns the result to the output stream, filling 
        /// the outgoing properties.
        /// </summary>
        /// <param name="mimeType">The MIME type string reference.</param>
        /// <param name="inProperties">The ingoing properties.</param>
        /// <param name="inStream">The input stream.</param>
        /// <param name="outProperties">The outgoing properties.</param>
        /// <param name="outStream">The output stream.</param>
        /// <remarks>
        /// The handler should not dispose the provided streams.
        /// </remarks>
        public void Handle(ref string mimeType,
            Dictionary<String, String> inProperties,
            Stream inStream,
            Dictionary<String, String> outProperties,
            Stream outStream)
        {
            if(!inProperties.ContainsKey("FileGuid"))
                throw Err.Of(this).NotSpecified("FileGuid").Ex();
            if(!inProperties.ContainsKey("CID"))
                throw Err.Of(this).NotSpecified("CID").Ex();

            var cid = inProperties["CID"].ParseAs<Guid>();
            if(cid == Guid.Empty)
                throw Err.Of(this).NotValid("CID").Ex();
            var sid = inProperties.ContainsKey("SID")
                ? inProperties["SID"].ParseAs<Guid>()
                : Guid.Empty;

            var fileGuid = inProperties["FileGuid"].ParseAs<Guid>();
            if(fileGuid == Guid.Empty)
                throw Err.Of(this).NotValid("FileGuid").Ex();

            using(var ioc = _infrastructure.DependencyResolver())
            {
                var processor = ioc.Resolve<IOperationProcessor>().Init(new WorkingContext
                {
                    CID = cid,
                    SID = sid,
                    IsSafe = false
                });

                try
                {
                    var file = processor.Execute(new GetFileByGuid
                    {
                        ThrowsException = true,
                        Guid = fileGuid
                    }).Result;
                    processor.Execute(new WriteFile
                    {
                        Guid = file.Guid,
                        InStream = inStream
                    });
                    processor.Commit();
                }
                catch
                {
                    processor.Rollback();
                    throw;
                }
            }
            mimeType = String.Empty;
        }

        #endregion
    }
}
